#include <iostream>
#include <zinx.h>
#include <unistd.h>
using namespace std;

//还是实现 标准输入的echo ，标准输入读到什么东西，标准输出就要输出什么东西
class StdinChannel : public Ichannel
{
public:
    /*通道初始化函数，一般地，开发者应该重写这个函数实现打开文件和一定的参数配置
     *  该函数会在通道对象添加到zinxkernel时被调用*/
    virtual bool Init()
    {
        //在上树前会执行
        //实现通道的初始化，初始成功的前提下应该要返回true，否则返回false
        return true;
    }

    /*读取数据， 开发者应该根据目标文件不同，重写这个函数，以实现将fd中的数据读取到参数_string中
     *  该函数会在数据源所对应的文件有数据到达时被调用*/
    virtual bool ReadFd(std::string &_input)
    {
        //当文件描述符触发 EPOLLIN的时候会被调用
        char buf[1024];
        memset(buf,0,sizeof(buf));
        int ret = read(STDIN_FILENO,buf,sizeof(buf));
        //顺便直接输出到标准输出上
        write(STDOUT_FILENO,buf,ret);
        //文件读取成功的情况下，应该要返回true
        return true;
    }

    /*写出数据， 开发者应该将数据写出的操作通过重写该函数实现
     *  该函数会在调用zinxkernel::sendout函数后被调用（通常不是直接调用而是通过多路复用的反压机制调用）*/
    virtual bool WriteFd(std::string &_output)
    {
        //当文件描述符触发EPOLLOUT的时候回被调用
        return false;
    }

    /*通道去初始化，开发者应该在该函数回收相关资源
     *  该函数会在通道对象从zinxkernel中摘除时调用*/
    virtual void Fini()
    {
        //在下树之后会去执行
        //通道对象销毁的时候会调用这个函数来完成一些清理工作
        //目前stdin不用做什么工作
    }

    /*获取文件描述符函数， 开发者应该在该函数返回当前关心的文件，
     *  一般地，开发者应该在派生类中定义属性用来记录数据来记录当前IO所用的文件，在此函数中只是返回该属性*/
    virtual int GetFd()
    {
        //上树时候框架会调用这个函数来确定要关注哪个文件描述符
        //告诉框架，当前通道关注的是哪个文件描述符
        return STDIN_FILENO;
    }
    /*获取通道信息函数，开发者可以在该函数中返回跟通道相关的一些特征字符串，方便后续查找和过滤*/
    virtual std::string GetChannelInfo()
    {
        //给当前通道起个名字
        return "StdinChannel";
    }
    /*获取下一个处理环节，开发者应该重写该函数，指定下一个处理环节
     *  一般地，开发者应该在该函数返回一个协议对象，用来处理读取到的字节流*/
    virtual AZinxHandler *GetInputNextStage(BytesMsg &_oInput)
    {
        return nullptr;
    }
}*poStdinChannel=new StdinChannel;
int main()
{
    //1 初始化，调用了 epoll_create
    ZinxKernel::ZinxKernelInit();

    //2 业务处理
    //将通道添加到框架中进行监听 调用了 epoll_ctl  上树  
    ZinxKernel::Zinx_Add_Channel(*poStdinChannel);

    //生命循环          调用了 epoll_wait
    ZinxKernel::Zinx_Run();

    //3 垃圾回收        调用了create
    ZinxKernel::ZinxKernelFini();

    return 0;
}
